package com.npf.imgserver.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import com.npf.imgserver.common.base.ResultBase;
import com.npf.imgserver.common.constant.Constants;
import com.npf.imgserver.common.enums.ResultCodeEnum;
import com.npf.imgserver.dao.ImgInfoMapper;
import com.npf.imgserver.entity.Customer;
import com.npf.imgserver.entity.ImgInfo;
import com.npf.imgserver.service.api.CustomerService;
import com.npf.imgserver.service.api.ImgInfoService;
import com.npf.imgserver.thread.GenerateImageThreadAsyc;
import com.npf.imgserver.thread.SaveImgThreadAsyc;
import com.npf.imgserver.utils.DateUtil;
import com.npf.imgserver.utils.ImgUtil;
import com.npf.imgserver.utils.StringUtil;
import com.npf.imgserver.vo.ImgRequestVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author nipengfei
 * @since 2018-09-23
 */
@Service(value = "imgInfoService")
public class ImgInfoServiceImpl extends ServiceImpl<ImgInfoMapper, ImgInfo> implements ImgInfoService {

    @Autowired
    private CustomerService customerService;
    @Autowired
    private ImgInfoMapper imgInfoMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultBase imgBase64UpLoad(ImgRequestVo requestVo) throws Exception {
        ResultBase resultBase = new ResultBase(ResultCodeEnum.SUCCESS);
        if (!StringUtil.isEmpty(requestVo)) {
            //接收参数
            String appKey = requestVo.getAppKey();
            String imgBase64 = requestVo.getImgBase64();
            if (StringUtil.isBlank(appKey) || StringUtil.isBlank(imgBase64)) {
                resultBase.setCodeEnum(ResultCodeEnum.IMG_INFO_PARAM_DEFECT);
            } else {
                //校验appKey
                Customer customer = customerService.queryCustomerByAppKey(appKey);
                if (ObjectUtils.isEmpty(customer)) {
                    resultBase.setCodeEnum(ResultCodeEnum.APP_KEY_ERROR);
                    return resultBase;
                } else if (customer.getIsLock() == 1 || customer.getIsDelete() == 1) {
                    //接入商 已被禁用或删除
                    resultBase.setCodeEnum(ResultCodeEnum.CUSTOMER_LOCK_OR_DELETE);
                    return resultBase;
                }
                //校验图片base64格式信息
                boolean imageFromBase64 = ImgUtil.isImageFromBase64(imgBase64);
                Integer imgSize = ImgUtil.imageSize(imgBase64);
                if (!imageFromBase64) {
                    //非图片格式
                    resultBase.setCodeEnum(ResultCodeEnum.IMG_INFO_FORMATTING_ERROR);
                    return resultBase;
                } else if (imgSize > Constants.IMG_CONTENT_LIMIT) {
                    //图片大小超限制
                    resultBase.setCodeEnum(ResultCodeEnum.IMG_INFO_OVERSIZE);
                    return resultBase;
                }
                //操作图片
                String mouth = DateUtil.getDate(DateUtil.DATE_FORMAT_YYYYMM);
                String day = DateUtil.getDate(DateUtil.DATE_FORMAT_YYYYMMDD);
                //接入商人编号
                Long customerId = customer.getCustomerId();
                String imgPath = Constants.IMG_UPLOAD_URL + File.separator + String.valueOf(customerId) + File.separator + mouth + File.separator + day + File.separator;
                File file = new File(imgPath);
                if (!file.exists()) {
                    file.mkdirs();
                }
                String imgName = String.valueOf(System.currentTimeMillis()) + Constants.IMG_SUFFIX;
                String imgFilePath = imgPath + imgName;
                //异步输出图片文件
                GenerateImageThreadAsyc generateImageThread = new GenerateImageThreadAsyc();
                generateImageThread.setImgBase64(imgBase64);
                generateImageThread.setImgFilePath(imgFilePath);
                generateImageThread.run();
                //回参 img地址
                //String imgUrl = Constants.HOST_IP + Constants.IMG_PATH_URL + File.separator + String.valueOf(customerId) + File.separator + mouth + File.separator + day + File.separator + imgName;
                String imgUrl = Constants.HOST_IP + Constants.IMG_PATH_URL + Constants.WINDOWS_SEPARATOR + String.valueOf(customerId) + Constants.WINDOWS_SEPARATOR + mouth + Constants.WINDOWS_SEPARATOR + day + Constants.WINDOWS_SEPARATOR + imgName;
                //异步存储图片信息
                SaveImgThreadAsyc saveImgThreadAsyc = new SaveImgThreadAsyc();
                customer.setImgUrl(imgUrl);
                saveImgThreadAsyc.setCustomer(customer);
                ExecutorService executorService = Executors.newSingleThreadExecutor();
                Future<Integer> future = executorService.submit(saveImgThreadAsyc);
                try {
                    //阻塞主线程  等待子线程执行结束
                    future.get();
                } catch (Exception e) {
                    //异常时清理已输出的图片信息 防止异常数据磁盘空间占用
                    file = new File(imgFilePath);
                    if (file.exists()) {
                        file.delete();
                    }
                    if (e instanceof InterruptedException) {
                        throw new Exception("图片信息保存线程中断");
                    } else if (e instanceof ExecutionException) {
                        throw new Exception("图片信息保存线程失败");
                    } else {
                        throw new Exception("其他异常");
                    }
                } finally {
                    executorService.shutdown();
                }

                Map<String, Object> map = Maps.newHashMap();
                map.put("imgUrl", imgUrl);
                resultBase.setData(map);
            }
        } else {
            //入参为空
            resultBase.setCodeEnum(ResultCodeEnum.IMG_INFO_IS_NULL);
        }
        return resultBase;
    }

    @Override
    public Integer saveImgInfo(ImgInfo imgInfo) {
        return imgInfoMapper.insert(imgInfo);
    }

    @Override
    public List<ImgInfo> queryImgInfo() {
        return imgInfoMapper.selectList(new QueryWrapper<ImgInfo>().orderByDesc("create_date"));
    }
}
